package com.polaris.live.ui.live.activity

import android.app.Activity
import android.os.Bundle
import android.view.MotionEvent
import android.view.TextureView
import android.view.View
import android.view.WindowManager
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.Utils
import com.bumptech.glide.Glide
import com.polaris.live.R
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.cacha.UserManager.ALBUM_INFORMATION
import com.polaris.live.common.cacha.UserManager.DECORATIVE_DISPLAY
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.constant.ServerConfig
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.mvvm.base2.BaseVbActivity
import com.polaris.live.common.network.parseState
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.UserConst
import com.polaris.live.databinding.ActivityCallVideoBinding
import com.polaris.live.im.sfs.bean.live.CallSignalingMessage
import com.polaris.live.im.sfs.bean.live.ext.UserBasicVo
import com.polaris.live.manager.LiveStateManager
import com.polaris.live.resp.back_resp.CallStartResp
import com.polaris.live.resp.back_resp.CallVo
import com.polaris.live.resp.back_resp.RecognizeModel
import com.polaris.live.resp.event.PartyExitEvent
import com.polaris.live.ui.live.fragment.CallAnswerFragment
import com.polaris.live.ui.live.fragment.CallBalanceFragment
import com.polaris.live.ui.live.fragment.CallVideoFragment
import com.polaris.live.ui.live.fragment.GameCallVideoFragment
import com.polaris.live.ui.live.fragment.base.OnGestureListener
import com.polaris.live.ui.live.proxy.LiveStreamProxy
import com.polaris.live.ui.live.proxy.LiveTranslationProxy
import com.polaris.live.ui.live.widget.listener.OnBackPressedListener
import com.polaris.live.ui.live.widget.listener.OnCallAnswerListener
import com.polaris.live.ui.live.widget.listener.OnCallEventListener
import com.polaris.live.ui.live.widget.listener.OnCallTranslationListener
import com.polaris.live.ui.live.widget.listener.OnGameCallListener
import com.polaris.live.ui.live.widget.listener.OnLiveCallCallback
import com.polaris.live.ui.live.widget.listener.OnPlayFirstFrameListener
import com.polaris.live.ui.live.widget.listener.OnPublishFirstFrameListener
import com.polaris.live.ui.live.widget.listener.OnTranslationChangeListener
import com.polaris.live.utils.fragment.attachFragment
import com.polaris.live.utils.getBooleanOrString
import com.polaris.live.utils.getIntOrString
import com.polaris.live.utils.image.loadImage
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import com.polaris.live.utils.zego.LiveActivityIdentifier
import com.polaris.live.utils.zego.LiveEngineManage
import com.polaris.live.viewmodel.live.CallVideoViewModel
import im.zego.zegoexpress.constants.ZegoPublisherState
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject

/**
 * CallVideoActivity
 *
 * @author Created by lucas on 2023/11/14 09:34
 * @since 1.0.0
 */
class CallVideoActivity : BaseVbActivity<CallVideoViewModel, ActivityCallVideoBinding>(),
    OnCallAnswerListener,
    OnPublishFirstFrameListener,
    OnPlayFirstFrameListener,
    OnLiveCallCallback,
    OnCallTranslationListener,
    OnTranslationChangeListener,
    OnGameCallListener {

    private val mFromType by lazy {
        intent.getIntOrString(LiveConst.Params.CALL_FROM_TYPE, UserConst.From.UNKNOWN)
    }
    private val mLastFromType by lazy {
        intent.getIntOrString(LiveConst.Params.CALL_LAST_FROM_TYPE, UserConst.LastFrom.UNKNOWN)
    }
    private val mCallRole by lazy {
        intent.getIntOrString(LiveConst.Params.CALL_ROLE, -1)
    }
    private val mNeedAgree by lazy {
        intent.getBooleanOrString(LiveConst.Params.CALL_NEED_AGREE, false)
    }
    private val mCallBean by lazy {
        intent.getParcelableExtra<CallStartResp>(LiveConst.Params.CALL_BEAN)
    }
    private val mCallMessage by lazy {
        intent.getParcelableExtra<CallSignalingMessage>(LiveConst.Params.CALL_MESSAGE)
    }
    private val mOtherUserBasic by lazy {
        intent.getParcelableExtra<UserBasicVo>(LiveConst.Params.CALL_USER_BASIC)
    }

    private var mCurrentFragment: Fragment? = null

    private var mIsGameCall = false

    //获取接听通话fragment标签嵌入
    private fun getCallAnswerFragment(callMessage: CallSignalingMessage): CallAnswerFragment {
        return supportFragmentManager.attachFragment(R.id.fl_fragment) {
            CallAnswerFragment().apply {
                arguments = bundleOf(
                    LiveConst.Params.CALL_MESSAGE to callMessage
                )
            }
        }.apply {
            setOnCallAnswerListener(this@CallVideoActivity)
        }
    }

    //获取余额不足通话fragment标签嵌入
    private fun getCallBalanceFragment(callBean: CallStartResp): CallBalanceFragment {
        return supportFragmentManager.attachFragment(R.id.fl_fragment) {
            CallBalanceFragment().apply {
                arguments = bundleOf(
                    LiveConst.Params.CALL_BEAN to callBean,
                    LiveConst.Params.CALL_FROM_TYPE to mFromType,
                    LiveConst.Params.CALL_LAST_FROM_TYPE to mLastFromType
                )
            }
        }.apply {
            setOnCallAnswerListener(this@CallVideoActivity)
        }
    }

    private val mLiveStreamProxy by lazy {
        LiveStreamProxy(
            LiveActivityIdentifier.CALL_VIDEO_ACTIVITY,
            this,
            mViewModel,
            LiveEngineManage.getEngine()
                ?: throw IllegalArgumentException("A fatal exception occurred, the video engine is not initialized"),
            mBinding.tvMinor,
            mBinding.tvMain,
            mBinding.tvMinor,
            this,
            this,
            null,
        )
    }

    //同声传译
    private val mLiveTranslationProxy by lazy { LiveTranslationProxy(this) }

    override fun initImmersionBar() {
    }

    override fun initView(savedInstanceState: Bundle?) {
        if (mCallRole == -1) {
            finish()
            return
        }


        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        if (!ServerConfig.isTestServer()) {
            window.setFlags(
                WindowManager.LayoutParams.FLAG_SECURE,
                WindowManager.LayoutParams.FLAG_SECURE
            )
        }

        LiveStateManager.changeStateForce(LiveConst.State.CALL)

        if (mCallRole == LiveConst.CallRole.ANSWER) {
            //外部如果没有传入直接返回，说明数据存在问题
            val callMessage = mCallMessage
            if (callMessage == null) {
                onStopCall()
                return
            }
            mIsGameCall = !mCallMessage?.getCallVo()?.gameMiniId.isNullOrEmpty()
            if (mNeedAgree) {
                toAnswer(callMessage)
            } else {
                toCall(mCallBean, mCallMessage)

                //这里调用同意接听接口
                mViewModel.answerCall(callMessage, LiveConst.AnswerType.AGREE)
            }
        } else {
            //外部如果没有传入直接返回，说明数据存在问题
            val callBean = mCallBean
            if (callBean == null) {
                onStopCall()
                return
            }
            mIsGameCall = !callBean.call.gameMiniId.isNullOrEmpty()
            mViewModel.getInfoUser(callBean.answer.userId, ALBUM_INFORMATION, DECORATIVE_DISPLAY)
            mBinding.cvCover.visibility = View.VISIBLE
            Glide.with(this)
                .loadImage(callBean.cover ?: callBean.answer.avatar)
                .centerCrop()
                .into(mBinding.ivCover)

            //余额不足需要做特殊处理
            if (callBean.call.status == LiveConst.CallState.INSUFFICIENT_BALANCE) {
                toBalance(callBean)
            } else {
                toCall(mCallBean, mCallMessage)
            }
        }

        initObserver()
        initListener()
    }

    private val onAppStatusChangedListener = object : Utils.OnAppStatusChangedListener {
        override fun onForeground(activity: Activity?) {
            if (!mViewModel.isForegroundClose) {
                mViewModel.callInfo
                    ?.takeIf { it.status == LiveConst.CallState.OVER }
                    ?.run { selectJump(this, mViewModel.callBean, mViewModel.callMessage) }

                finish()
            }
        }

        override fun onBackground(activity: Activity?) {
        }
    }

    private fun initObserver() {
        AppUtils.registerAppStatusChangedListener(onAppStatusChangedListener)

        mViewModel.callAnswerLiveData.observe(this) { (callMessage, callBean) ->
            getCurrentEventListener()?.onAnswerSuccess(callBean, callMessage)
        }
        mViewModel.infoLiveData.observe(this) { state ->
            parseState(state, {
                mBinding.liveBanner.setCoverBanner(it, this)
            })
        }
    }

    private fun initListener() {
        mBinding.cvMinor.setOnSingleClickListener {
            mLiveStreamProxy.switchPlayView()
        }
    }

    //转到接听页面
    private fun toAnswer(callMessage: CallSignalingMessage) {
        mCurrentFragment = getCallAnswerFragment(callMessage)
    }

    //转到余额不足页面
    private fun toBalance(callBean: CallStartResp) {
        mCurrentFragment = getCallBalanceFragment(callBean)
        if (callBean.call.liveStreamId != null) {
            mLiveStreamProxy.startPlayStream(callBean.call.liveStreamId)
            mBinding.cvCover.visibility = View.GONE
        }
        mLiveStreamProxy.userFrontCamera()
        mLiveStreamProxy.startPreview()
    }

    //转到真实通话页面
    private fun toCall(callBean: CallStartResp?, callMessage: CallSignalingMessage?) {
        val callInfo = callBean?.call ?: callMessage?.getCallVo()
        if (callInfo == null) {
            //这里理论上不可能出现
            finish()
            return
        }

        //先删除之前的fragment
        mCurrentFragment?.also {
            supportFragmentManager.beginTransaction()
                .remove(it)
                .commit()
        }
        val fragment = if (mIsGameCall) {
            supportFragmentManager.attachFragment(R.id.fl_fragment) {
                GameCallVideoFragment().apply {
                    arguments = bundleOf(
                        LiveConst.Params.CALL_BEAN to callBean,
                        LiveConst.Params.CALL_MESSAGE to callMessage,
                        LiveConst.Params.CALL_INFO to callInfo,
                        LiveConst.Params.CALL_USER_BASIC to mOtherUserBasic,
                    )
                    setOnTranslateChangeListener(this@CallVideoActivity)
                    setOnGameCallListener(this@CallVideoActivity)
                }
            }
        } else {
            supportFragmentManager.attachFragment(R.id.fl_fragment) {
                CallVideoFragment().apply {
                    arguments = bundleOf(
                        LiveConst.Params.CALL_BEAN to callBean,
                        LiveConst.Params.CALL_MESSAGE to callMessage,
                        LiveConst.Params.CALL_INFO to callInfo,
                        LiveConst.Params.CALL_USER_BASIC to mOtherUserBasic,
                    )
                    setOnTranslateChangeListener(this@CallVideoActivity)
                }
            }
        }
        mCurrentFragment = fragment
        fragment.setOnLiveCallCallback(this@CallVideoActivity)
        mLiveStreamProxy.startPublishStream(callInfo.pushStreamId)
        mLiveStreamProxy.startPlayStream(callInfo.playStreamId)
    }

    override fun onPublishFirstFrame() {

    }

    override fun onPublisherStateUpdate(
        streamID: String?,
        state: ZegoPublisherState?,
        errorCode: Int,
        extendedData: JSONObject?,
    ) {
        if (errorCode != 0) {
            //推流状态出错
        }
        when (state) {
            ZegoPublisherState.PUBLISHING -> {
                //正在推流中
            }

            ZegoPublisherState.NO_PUBLISH -> {
                //未推流
            }

            ZegoPublisherState.PUBLISH_REQUESTING -> {
                //正在请求推流中
            }

            else -> {}
        }

    }

    override fun onPlayFirstFrame() {
        EventBus.getDefault().post(PartyExitEvent(true))
        //拿到对方的帧，代表通话正式开始
        mCurrentFragment?.also {
            if (it is OnPlayFirstFrameListener) {
                it.onPlayFirstFrame()
            }
        }

        mBinding.cvCover.visibility = View.GONE
        mBinding.cvPhotos.visibility = View.GONE
    }

    override fun agreeCall(callInfo: CallStartResp) {
        EventBus.getDefault().post(PartyExitEvent(true))
        toCall(callInfo, mCallMessage)
    }

    override fun refuseCall() {
        //拒绝通话直接结束
        onStopCall()
        mLiveStreamProxy.initiativeStopPublishStream()
    }

    override fun stopStream() {
        mLiveStreamProxy.stopPlayStream()
        if (mBinding.liveBanner.getPhoneNum() != 0 && mCallBean?.answer?.living == AppConst.YES) {
            mBinding.cvCover.visibility = View.GONE
            mBinding.cvPhotos.visibility = View.VISIBLE
        } else {
            mBinding.cvCover.visibility = View.VISIBLE
            mBinding.cvPhotos.visibility = View.GONE
        }
    }

    override fun onCallStop(
        callInfo: CallVo?,
        callBean: CallStartResp?,
        callMessage: CallSignalingMessage?,
        isForeground: Boolean,
    ) {
        mViewModel.isForegroundClose = isForeground
        mViewModel.callBean = callBean
        mViewModel.callMessage = callMessage
        mViewModel.callInfo = callInfo
        if (callInfo != null && callInfo.status == LiveConst.CallState.OVER) {
            if (mViewModel.isForegroundClose) {
                selectJump(callInfo, callBean, callMessage)
            }
        }
        onStopCall(mViewModel.isForegroundClose)
    }

    fun selectJump(
        callInfo: CallVo,
        callBean: CallStartResp?,
        callMessage: CallSignalingMessage?,
    ) {
        if (callInfo.payUserId == UserManager.getUserId()) {
            Router.builder(RoutePath.LIVE_PAY_CALL_END_ACTIVITY)
                .withAny(LiveConst.Params.CALL_INFO, callInfo)
                .withAnyNullable(LiveConst.Params.CALL_BEAN, callBean)
                .withAnyNullable(LiveConst.Params.CALL_MESSAGE, callMessage)
                .navigation(this)
        } else {
            Router.builder(RoutePath.LIVE_GAIN_CALL_END_ACTIVITY)
                .withAny(LiveConst.Params.CALL_INFO, callInfo)
                .withAnyNullable(LiveConst.Params.CALL_BEAN, callBean)
                .withAnyNullable(LiveConst.Params.CALL_MESSAGE, callMessage)
                .navigation(this)
        }
    }

    override fun onChangeCamera() {
        mLiveStreamProxy.changeCamera()
    }

    override fun onTranslating(model: RecognizeModel) {
        getCurrentEventListener()?.onTranslating(model)
    }

    override fun onTranslated(model: RecognizeModel) {
        getCurrentEventListener()?.onTranslated(model)
    }

    //同声传译开关
    override fun onTranslationSwitch(isOpen: Boolean, needUnInit: Boolean) {
        if (isOpen) {
            mLiveTranslationProxy.startTranslation()
        } else {
            mLiveTranslationProxy.stopTranslation(needUnInit)
        }
    }

    //初始化同声传译
    override fun onInitTranslation(
        key: String,
        translationLanguage: String,
        speechLanguage: String,
    ) {
        mLiveTranslationProxy.initKey(key, translationLanguage, speechLanguage)
    }

    //修改同声传译语言
    override fun onTranslationLanguage(language: String) {
        mLiveTranslationProxy.setTranslationLanguage(language)
    }

    override fun onSetSpeechLanguage(language: String) {
        mLiveTranslationProxy.setSpeechLanguage(language)
    }

    private fun onStopCall(isForeground: Boolean = true) {
        //状态回归正常
        LiveStateManager.changeState(LiveConst.State.NONE)
        if (isForeground) {
            finish()
        }
    }

    override fun setGameCallView(publishView: TextureView, playView: TextureView) {
        mLiveStreamProxy.setStartGameCallView(publishView, playView)
    }

    override fun onGameChangeCamera() {
        mLiveStreamProxy.changeCamera()
    }

    override fun onGameOpenCloseCamera(mCloseCamera: Boolean, publishView: TextureView) {
        mLiveStreamProxy.onGameOpenCloseCamera(mCloseCamera, publishView)
    }

    override fun onGameOtherOpenCloseCamera(mCloseCamera: Boolean, publishView: TextureView) {
        mLiveStreamProxy.onGameOtherOpenCloseCamera(mCloseCamera, publishView)
    }

    override fun onDestroy() {
        super.onDestroy()
        AppUtils.unregisterAppStatusChangedListener(onAppStatusChangedListener)
    }

    private fun getCurrentEventListener(): OnCallEventListener? {
        val fragment = mCurrentFragment
        return if (fragment is OnCallEventListener) {
            fragment
        } else {
            null
        }
    }

    override fun onBackPressed() {
        val currentFragment = mCurrentFragment
        if (currentFragment is OnBackPressedListener) {
            if (!currentFragment.onBackPressed()) {
                super.onBackPressed()
            }
        } else {
            super.onBackPressed()
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        val currentFragment = mCurrentFragment
        return if (currentFragment is OnGestureListener) {
            currentFragment.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev)
        } else {
            super.dispatchTouchEvent(ev)
        }
    }
}